package office.document;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
import lombok.extern.slf4j.Slf4j;
import office.document.core.domain.DocumentHeadDO;
import office.document.core.domain.DocumentInfoDO;
import office.document.core.domain.TextLineExtractDO;
import office.document.pdfbox.PdfExtractUtil;
import office.document.pdfbox.PdfOutlineUtil;
import wiki.xsx.core.pdf.doc.XEasyPdfDocument;
import wiki.xsx.core.pdf.handler.XEasyPdfHandler;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 描述
 *
 * @author: zhanglu
 * @date: 2023/7/31 18:49
 * @modify: 修改人信息, 修改内容 2023/7/31 18:49
 */
@Slf4j
public class LuTest {

    public static void main(String[] args) {
        //word测试
        String file = "/Users/zhanglu/Desktop/tmp/docx4j/source.docx";
//        List<DocumentHeadDO> heads = WordOutlineUtil.getHeads(FileUtil.readBytes(file));
//        System.out.println("获取word大纲");
//        System.out.println(JSONUtil.toJsonStr(heads));
//        DocumentHeadDO head = WordOutlineUtil.buildHeadTree(heads);
//        System.out.println("获取word大纲树");
//        System.out.println(JSONUtil.toJsonStr(head));

        //pdf测试
        String pdfFile = "/Users/zhanglu/Desktop/未命名3.pdf";

//        //获取大纲列表
//        List<DocumentHeadDO> bookmarks = PdfOutlineUtil.getDocumentBookmarks(FileUtil.readBytes(pdfFile));
//        System.out.println("获取pdf大纲");
//        System.out.println(JSONUtil.toJsonStr(bookmarks));
//        //获取大纲树形列表
//        DocumentHeadDO bookmarkTree = PdfOutlineUtil.getDocumentBookmarkTree(FileUtil.readBytes(pdfFile));
//        System.out.println("获取pdf大纲树");
//        System.out.println(JSONUtil.toJsonStr(bookmarkTree));
//
//        //获取表格数据
//        TableExtractDO table = PdfExtractUtil.getTable(FileUtil.readBytes(pdfFile), 63);
//        System.out.println("获取pdf表格数据");
//        System.out.println(JSONUtil.toJsonStr(table));
//        FileUtil.writeBytes(PdfExtractUtil.generateExcel(table), "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册2.xlsx");
//        System.out.println("根据表格数据生成excel，结束");
//        FileUtil.writeBytes(PdfExtractUtil.smallPdfToExcel(FileUtil.readBytes("/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册3/63.pdf")), "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册2_1.xlsx");
//        System.out.println("pdf小文件转为excel表格01，结束");
//        FileUtil.writeBytes(PdfExtractUtil.smallPdfToExcel(FileUtil.readBytes("/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册3/16.pdf")), "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册2_2.xlsx");
//        System.out.println("pdf小文件转为excel表格02，结束");
//
        //指定pdf页转word (响应时长，(3 + n)秒)
        byte[] bytes = PdfExtractUtil.pdfToWordByPageNo(FileUtil.readBytes(pdfFile), Arrays.asList(7));
        FileUtil.writeBytes(bytes, "/Users/zhanglu/Desktop/未命名3.docx");
        System.out.println("指定pdf页转word，结束");
//
//        //指定pdf起止页转word (响应时长，(3 + n)秒)
//        bytes = PdfExtractUtil.pdfToWordByPageNo(FileUtil.readBytes(pdfFile), 1, 95);
//        FileUtil.writeBytes(bytes, "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册2_2.docx");
//        System.out.println("指定pdf页转word，结束");
//
//        //pdf小文件转为word
//        FileUtil.writeBytes(PdfExtractUtil.smallPdfToWord(FileUtil.readBytes("/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册3/2.pdf")), "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册3.docx");
//        System.out.println("pdf小文件转为word，结束");

//        //pdf文本提取
//        List<TextLineExtractDO> textInfos = PdfExtractUtil.textLineExtractByPageNo(FileUtil.readBytes(pdfFile), Arrays.asList(27));
//        System.out.println(JSONUtil.toJsonStr(textInfos));
//        textInfos = PdfExtractUtil.textLineExtractByPageNo(FileUtil.readBytes(pdfFile), Arrays.asList(1,3,4));
//        System.out.println(JSONUtil.toJsonStr(textInfos));
//        List<String> lines = PdfExtractUtil.textLineExtractByPageNo(FileUtil.readBytes(pdfFile), 1, 4);
//        System.out.println(JSONUtil.toJsonStr(lines));
//        textInfos = PdfExtractUtil.textLineExtractByPageNo(FileUtil.readBytes(pdfFile), Arrays.asList());
//        System.out.println(JSONUtil.toJsonStr(textInfos));

        //pdf元数据信息获取
//        DocumentInfoDO documentInfo = PdfExtractUtil.getDocumentInfo(FileUtil.readBytes(pdfFile));
//        System.out.println(JSONUtil.toJsonStr(documentInfo));

//        for (int i = 0; i < 1; i++) {
//            int finalI = i;
//            new Thread(() -> {
//                long s1 = System.currentTimeMillis();
//                byte[] bytes = pdfToWordByPageNo(FileUtil.readBytes(pdfFile), 1, 90);
//                long s2 = System.currentTimeMillis();
//                FileUtil.appendUtf8String(Thread.currentThread().getName() + "---" + (s2 - s1),
//            "/Users/zhanglu/Desktop/tmp/pdfbox/res.txt");
//                FileUtil.writeBytes(bytes, "/Users/zhanglu/Desktop/tmp/pdfbox/res" + finalI + ".docx");
//            }).start();
//        }

    }

    /**
     * 指定pdf起止页转word
     * - 将大的pdf文件拆分成单页的pdf文件
     * - 根据输入的页号将选中的pdf转成docx
     * - 将docx合并为一个完整的docx
     *
     * @param pdfBytes    pdf格式字节数组
     * @param startPageNo 起始页号，若输入相同的页号，提取输入页
     * @param endPageNo   起始页号，若输入相同的页号，提取输入页，间隔范围最大20个元素
     * @return docx格式字节数组
     */
    public static byte[] pdfToWordByPageNo(byte[] pdfBytes, Integer startPageNo, Integer endPageNo) {
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        String tmpDir = FileUtil.getTmpDirPath() + File.separator + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN);
        try {
            //检查输入参数
            Assert.isTrue(ObjectUtil.isNotEmpty(startPageNo), "请输入起始页号");
            Assert.isTrue(ObjectUtil.isNotEmpty(startPageNo), "请输入结束页号");
            //检查指定页的范围，不能超过最大限制
            Assert.isTrue((endPageNo - startPageNo) <= PdfExtractUtil.PAGE_MAX_COUNT, "无效的参数，页数超出限制，最大{}页", PdfExtractUtil.PAGE_MAX_COUNT);
            //加载pdf
            XEasyPdfDocument document = XEasyPdfHandler.Document.load(new ByteArrayInputStream(pdfBytes));
            Assert.isTrue(startPageNo >= 1, "无效的参数，起始页号必须大于等于1");
            Assert.isTrue(endPageNo <= document.getPageList().size(), "无效的参数，结束页号超出文档范围");
            //申请临时文件目录
            FileUtil.mkdir(tmpDir);
            //pdf拆分成单页
            document.splitter().split(tmpDir, "");
            //关闭x-esay-pdf流，后续采用spire技术处理
            document.close();
            List<byte[]> bytes = new ArrayList<>();
            for (int i = (startPageNo - 1); i < endPageNo; i++) {
                log.info("pdf to word : {}", tmpDir + File.separator + (i + 1) + ".pdf");
                //加载单页PDF文档
                PdfDocument pdf = new PdfDocument(tmpDir + File.separator + (i + 1) + ".pdf");
                //设置字体包路径
                PdfDocument.setCustomFontsFolders("/Users/zhanglu/Downloads/serif");
                //单页pdf转为word
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                pdf.saveToStream(out, FileFormat.DOCX);
                bytes.add(out.toByteArray());
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                pdf.close();
            }
            //word合并
            return PdfExtractUtil.mergeWords(bytes);
        } catch (Exception e) {
            log.error("指定pdf起止页转word异常", e);
        } finally {
            //删除临时目录
            FileUtil.del(tmpDir);
        }
        return new byte[0];
    }

}
